package com.zq.realms;

import com.zq.pojo.JwtToken;
import com.zq.service.impl.UserService;
import com.zq.utils.StatusEnum;
import com.zq.utils.TokenUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.shiro.SecurityUtils;
import org.apache.shiro.authc.AuthenticationException;
import org.apache.shiro.authc.AuthenticationInfo;
import org.apache.shiro.authc.AuthenticationToken;
import org.apache.shiro.authc.SimpleAuthenticationInfo;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.apache.shiro.subject.Subject;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

//自定义realm
@Slf4j
@Component
public class CustomerRealm extends AuthorizingRealm {
    @Autowired
    private UserService userService;
    //授权访问
    @Override
    protected AuthorizationInfo doGetAuthorizationInfo(PrincipalCollection principalCollection) {
        log.info("doGetAuthorizationInfo");
        SimpleAuthorizationInfo info=new SimpleAuthorizationInfo();
        //获得当前subject
        Subject subject= SecurityUtils.getSubject();
        //获得当前的principal,也就是认证完后我们放入的信息

        String username=(String) subject.getPrincipal();
        //添加权限
        info.addStringPermissions(userService.getPermissions(username));
        //添加角色
        info.addRole(userService.getRoles(username));

        return info;
    }

    //认证
    @Override
    protected AuthenticationInfo doGetAuthenticationInfo(AuthenticationToken authenticationToken) throws AuthenticationException {
        log.info("doGetAuthenticationInfo");
        String token=(String)authenticationToken.getCredentials();
        if(token==null){
            throw new AuthenticationException("token无效");
        }
        StatusEnum statusEnum = TokenUtil.verifyToken(token);
        if(statusEnum.equals(StatusEnum.EXPIRED)){
            throw new AuthenticationException("token过期");
        }
        if(statusEnum.equals(StatusEnum.FAILED)){
            throw new AuthenticationException("token无效");
        }
        String username= TokenUtil.getAccountByToken(token);
        log.info("登录用户为:{}",username);

        //交给AuthenticatingRealm使用CredentialsMatcher进行密码匹配，不配置的话则使用默认的SimpleCredentialsMatcher
        //用户名,凭证,realm name
        return new SimpleAuthenticationInfo(username,token,this.getName());
    }

    /*
     * 多重写一个support
     * 标识这个Realm是专门用来验证JwtToken，不负责验证其他的token（UsernamePasswordToken）
     * 必须重写此方法，不然Shiro会报错
     */
    @Override
    public boolean supports(AuthenticationToken token) {
        return token instanceof JwtToken;
    }

}
